terraform {
  required_providers {
    helm       = {
      source  = "hashicorp/helm"
      version = "2.1.2"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "2.1.0"
    }
    consul     = {
      source  = "hashicorp/consul"
      version = "2.11.0"
    }
    time       = {
      source  = "hashicorp/time"
      version = "0.7.1"
    }
  }
}

provider "helm" {
  kubernetes {
    config_path = var.k8s_config_path
  }
}

provider "kubernetes" {
  config_path    = var.k8s_config_path
  config_context = var.k8s_context
}

resource "helm_release" "consul" {
  chart      = "consul"
  repository = "https://helm.releases.hashicorp.com"
  name       = "consul-cluster"
  set {
    name  = "server.affinity"
    value = ""
  }
}

resource "time_sleep" "wait_for_consul_cluster" {
  depends_on = [helm_release.consul]
  create_duration = "30s"
}

data "kubernetes_service" "consul_serer" {
  depends_on = [
    helm_release.consul]
  metadata {
    name = "consul-cluster-consul-server"
  }
}


resource "kubernetes_service" "consul_public_service" {
  metadata {
    name = "consul-public-service"
  }
  spec {
    selector = data.kubernetes_service.consul_serer.spec[0].selector
    type     = "LoadBalancer"
    port {
      port        = 8500
      target_port = 8500
    }
  }
}

locals {
  consul_cluster_addr = "${data.kubernetes_service.consul_serer.metadata[0].name}.default.svc:8500"
  consul_public_addr  = "${kubernetes_service.consul_public_service.status[0].load_balancer[0].ingress[0].hostname}:8500"
}

provider "consul" {
  address = local.consul_public_addr
}

resource "consul_keys" "hello_key" {
  depends_on = [
    kubernetes_service.consul_public_service,
    time_sleep.wait_for_consul_cluster]

  key {
    path   = "hello"
    value  = "world"
    delete = true
  }
}

resource "kubernetes_config_map" "config_template" {
  depends_on = [
    consul_keys.hello_key]
  metadata {
    name = "consul-template-config"
  }
  data       = {
    "config.hcl" = <<EOT
consul {
  address = "${local.consul_cluster_addr}"

  auth {
    enabled = false
  }
}

log_level = "warn"
once = false
template {
  contents = "{{key \"hello\"}}"
  destination = "/config/out.cfg"
}
EOT
  }
}

resource "kubernetes_config_map" "loop_and_cat" {
  metadata {
    name = "loop-and-cat-script"
  }
  data = {
    "cat.sh" = <<EOT
while true
do
	cat /config/out.cfg
    printf "\n"
	sleep 3
done
EOT
  }
}

resource "kubernetes_pod" "consul_template" {
  metadata {
    name = "consul-template-sidecar"
  }
  spec {
    init_container {
      name    = "touch-cfg"
      image   = "busybox"
      volume_mount {
        mount_path = "/config"
        name       = "config"
      }
      command = [
        "touch"]
      args    = [
        "/config/out.cfg"]
    }
    container {
      name    = "echo"
      image   = "busybox"
      volume_mount {
        mount_path = "/config"
        name       = "config"
      }
      volume_mount {
        mount_path = "/script"
        name       = "cat-script"

      }
      command = [
        "/bin/sh",
        "-c"]
      args    = [
        "/script/cat.sh"]
    }
    container {
      name    = "consul-template"
      image   = "hashicorp/consul-template:alpine"
      command = [
        "consul-template"]
      args    = [
        "-config",
        "/consul_template/config.hcl"]
      volume_mount {
        mount_path = "/config"
        name       = "config"
      }
      volume_mount {
        mount_path = "/consul_template"
        name       = "consul-template"
      }
    }
    volume {
      name = "config"
      empty_dir {}
    }
    volume {
      name = "consul-template"
      config_map {
        name = kubernetes_config_map.config_template.metadata[0].name
      }
    }
    volume {
      name = "cat-script"
      config_map {
        name         = kubernetes_config_map.loop_and_cat.metadata[0].name
        default_mode = "0777"
      }
    }
  }
}
